<?php
if (!defined('BASEPATH')) exit('Нет доступа к скрипту');

class Users
{
    protected $_CI;
    protected $_DB;

    const CODE_USER_CREATE_DONE             = '00';
    const CODE_USER_AUTH_DONE               = '00';
    const CODE_USER_FORGOT_PWD_DONE         = '00';
    const CODE_USER_ACTIVATE_DONE           = '02';

    const CODE_USER_EXISTS_ERROR            = '01';
    const CODE_USER_ACTIVATE_ERROR          = '03';
    const CODE_USER_EMAIL_ERROR             = '04';
    const CODE_USER_NOT_ACTIVATE_ERROR      = '05';
    const CODE_USER_NOT_FOUND_ERROR         = '06';
    const CODE_USER_PASSWD_EMPTY_ERROR      = '07';
    const CODE_USER_FORGOT_PWD_SENT         = '08';
    const CODE_USER_FORGOT_PWD_ERROR        = '09';

    public function __construct()
    {
        $this->_CI =& get_instance();
        $this->_CI->load->database();
    }

    public function createUser($email, $password)
    {
        if ($this->isUserExists($email))  //check if email already registered
        {
            return ['status' => 'error', 'code' => Users::CODE_USER_EXISTS_ERROR];
        }
        else
        {
            $regDate = date("Y-m-d");
            $regTime = date("H:i:s");

            $this->_CI->db->insert('users', [
                'email' => $email,
                'passwd' => md5($password),
                'reg_date' => $regDate,
                'reg_time' => $regTime ,
            ]);

            $this->sendActivationMail($email, $password, $this->_CI->db->insert_id());

            $MailChimp = new MailChimp();
            $MailChimp->call('lists/subscribe', array(
                'id'                => '2a269d2ed0',
                'email'             => array('email' => $email),
                'double_optin'      => false,
                'update_existing'   => true,
                'replace_interests' => false,
                'send_welcome'      => false,
            ));

            return ['status' => 'done', 'code' => Users::CODE_USER_CREATE_DONE];
        }
    }

    public function loginUser ($email, $password)
    {
        $user = $this->getUserByEmailAndPass($email, $password);

        if (!$user)
            return ['status' => 'error', 'code' => Users::CODE_USER_NOT_FOUND_ERROR];

        if ($user->active == "N")
            return ['status' => 'error', 'code' => Users::CODE_USER_NOT_ACTIVATE_ERROR];

        $this->createUserSession($user);

        return ['status' => 'done', 'code' => Users::CODE_USER_AUTH_DONE];
    }

    public function logoutUser()
    {
        $this->destroyUserSession();
    }

    public function getUserByEmailAndPass($email, $pass)
    {
        $user = new stdClass();

        $this->_CI->db
            ->where(['email' => $email, 'passwd' => md5($pass)])
            ->select('id, email, reg_date, reg_time, active, status, group')
            ->from('users');

        $result = $this->_CI->db->get()->result();

        if (!$result)
            return FALSE;

        $result = $result[0];

        $user->id       = $result->id;
        $user->email    = $result->email;
        $user->regDate  = $result->reg_date;
        $user->regTime  = $result->reg_time;
        $user->active   = $result->active;
        $user->status   = $result->status;
        $user->group    = $result->group;

        return $user;
    }

    public function getUserByEmail($email)
    {
        $user = new stdClass();

        $this->_CI->db
            ->where(['email' => $email])
            ->select('id, email, reg_date, reg_time, active, status, group')
            ->from('users');

        $result = $this->_CI->db->get()->result();

        if (!$result)
            return FALSE;

        $result = $result[0];

        $user->id       = $result->id;
        $user->email    = $result->email;
        $user->regDate  = $result->reg_date;
        $user->regTime  = $result->reg_time;
        $user->active   = $result->active;
        $user->status   = $result->status;
        $user->group    = $result->group;

        return $user;
    }

    public function getUserById($userId)
    {
        $user = new stdClass();

        $this->_CI->db
            ->where(['id' => $userId])
            ->select('id, email, reg_date, reg_time, active, status, group')
            ->from('users');

        $result = $this->_CI->db->get()->result();

        if (!$result)
            return FALSE;

        $result = $result[0];

        $user->id       = $result->id;
        $user->email    = $result->email;
        $user->regDate  = $result->reg_date;
        $user->regTime  = $result->reg_time;
        $user->active   = $result->active;
        $user->status   = $result->status;
        $user->group    = $result->group;

        return $user;
    }

    public function activateUser($userId, $code)
    {
        $user = $this->getUserById($userId);

        if (!$user)
            return ['status' => 'error', 'code' => Users::CODE_USER_ACTIVATE_ERROR];

        $userCode = $this->getActivationCode($user->email);

        if ($code != $userCode)
        {
            return ['status' => 'error', 'code' => Users::CODE_USER_ACTIVATE_ERROR];
        }
        else
        {
            $this->_CI->db->where(['id' => $user->id])->update('users', ['active' => 'Y']);
            $this->createUserSession($user);

            $MailChimp = new MailChimp();
            $res = $MailChimp->call('lists/unsubscribe', array(
                'id'                => '2a269d2ed0',
                'email'             => array('email' => $user->email),
                "delete_member"     => true,
                "send_goodbye"      => false,
                "send_notify"       => false,
              ));

            $MailChimp->call('lists/subscribe', array(
                'id'                => 'b486f9e04c',
                'email'             => array('email' => $user->email),
                'double_optin'      => false,
                'update_existing'   => true,
                'replace_interests' => false,
                'send_welcome'      => false,
            ));

            return ['status' => 'done', 'code' => Users::CODE_USER_ACTIVATE_DONE];
        }
    }

    public function sendActivationMail($email, $passwd, $user_id)
    {
        $this->_CI->load->library('email');
        $this->_CI->email->set_newline("\r\n");

        $this->_CI->config->load('email');
        $emailCfg = $this->_CI->config->item('email_from');

        $activationLnk = $this->_CI->config->site_url() . 'profile/activate/' . $user_id . '/' . $this->getActivationCode($email, $passwd);

        $email_body = $this->_CI->load->view('activation_email', '', true);
        $email_body = str_replace(['%email%','%activationLnk%'],[$email,$activationLnk],$email_body);

        $this->_CI->email->from($emailCfg['email'], $emailCfg['name']);
        $this->_CI->email->to($email);
        $this->_CI->email->subject('KOZA: Активация учетной записи');
        $this->_CI->email->message($email_body);

        $this->_CI->email->send();
    }

    public function getActivationCode($email)
    {
        return substr(md5($email), 0, 10);
    }

    public function isUserExists($email)
    {
        $query = $this->_CI->db->get_where('users', array('email' => $email));

        foreach ($query->result() as $user)
        {
            if ($user->id)
                return true;
            else
                return false;
        }
    }

    public function createUserSession($user)
    {
        $browser = $_SERVER['HTTP_USER_AGENT'];
        $ip = $_SERVER['REMOTE_ADDR'];

        $this->_CI->db->insert('sessions', [
            'browser'   => $browser,
            'ip'        => $ip,
            'user_id'   => $user->id,
        ]);

        $session_id = $this->_CI->db->insert_id();
        setcookie("sid", $session_id, time()+2629743, '/');
    }

    public function readUserSession()
    {
        if (!isset($_COOKIE['sid']))
            return false;

        $sid = $_COOKIE['sid'];
        $session = $this->_CI->db->get_where('sessions', array('id' => $sid))->result();

        if (!$session)
            return false;

        $session = $session[0];

        //check session
        $browser = $_SERVER['HTTP_USER_AGENT'];
        $ip = $_SERVER['REMOTE_ADDR'];

        if ($session->browser != $browser || $session->ip != $ip)
            return false;

        $userId = $session->user_id;

        $user = $this->_CI->db->get_where('users', ['id' => $userId])->result();

        if (!$user)
            return false;

        $user = $user[0];
        $this->_CI->db->where('id', $user->id)->update('users',['last_login' => date("Y-m-d H:i:s")]);

        $sessionObj = new stdClass();
        $sessionObj->id = $session->id;
        $sessionObj->user = $user;

        return $sessionObj;
    }

    public function destroyUserSession()
    {
        if (!isset($_COOKIE['sid']))
            return false;

        $sid = $_COOKIE['sid'];

        $this->_CI->db->delete('sessions', array('id' => $sid));
        setcookie("sid", "", time()-3600, '/');
    }

    public function getUserIdByForgotCode($code)
    {
        $query = $this->_CI->db->get_where('users_forgot_pwd', ['flush_code' => $code])->result();

        if (!$query)
            return false;

        $userId = $query[0]->user_id;
        return $userId;
    }

    public function sendForgotMail($email)
    {
        //create forgot session
        $user = $this->getUserByEmail($email);

        if (!$user)
            return ['status' => 'done', 'code' => Users::CODE_USER_EMAIL_ERROR];

        $code = md5(md5(time() . microtime()) . md5(microtime()) . md5(time()));

        $this->_CI->db->insert('users_forgot_pwd', [
            'user_id'       => $user->id,
            'flush_code'    => $code,
        ]);

        $this->_CI->load->library('email');
        $this->_CI->email->set_newline("\r\n");

        $this->_CI->config->load('email');
        $emailCfg = $this->_CI->config->item('email_from');

        $forgotLnk = $this->_CI->config->site_url() . 'profile/forgotPwd/' . $code;

        $email_body = $this->_CI->load->view('forgot_email', '', true);
        $email_body = str_replace(['%email%','%forgotLnk%'],[$user->email,$forgotLnk],$email_body);

        $this->_CI->email->from($emailCfg['email'], $emailCfg['name']);
        $this->_CI->email->to($user->email);
        $this->_CI->email->subject('KOZA: Восстановление пароля');
        $this->_CI->email->message($email_body);

        $this->_CI->email->send();

        return ['status' => 'done', 'code' => Users::CODE_USER_FORGOT_PWD_SENT];
    }

    public function flushPassword($code, $password)
    {
        $userId = $this->getUserIdByForgotCode($code);
        if (!$userId) return ['status' => 'error1', 'code' => Users::CODE_USER_FORGOT_PWD_ERROR];

        $user = $this->getUserById($userId);
        if (!$user) return ['status' => 'error2', 'code' => Users::CODE_USER_FORGOT_PWD_ERROR];

        $this->_CI->db->where(['id' => $user->id])->update('users', ['passwd' => md5($password)]);
        $this->_CI->db->delete('users_forgot_pwd', array('user_id' => $user->id));

        return ['status' => 'done', 'code' => Users::CODE_USER_FORGOT_PWD_DONE];
    }
}